<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Echo 💡</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../../index.html" title="Chapter 1. Boost.Beast">
<link rel="up" href="../writing_composed_operations.html" title="Writing Composed Operations">
<link rel="prev" href="../writing_composed_operations.html" title="Writing Composed Operations">
<link rel="next" href="detect_ssl.html" title="Detect SSL 💡">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../writing_composed_operations.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../writing_composed_operations.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="detect_ssl.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="beast.using_io.writing_composed_operations.echo"></a><a class="link" href="echo.html" title="Echo 💡">Echo
        💡</a>
</h4></div></div></div>
<p>
          This example develops an initiating function called <span class="bold"><strong>echo</strong></span>.
          The operation will read up to the first newline on a stream, and then write
          the same line including the newline back on the stream. First we define
          the input parameters and results, then declare our initiation function.
          For our echo operation the only inputs are the stream and the completion
          token. The output is the error code which is usually included in all completion
          handler signatures.
        </p>
<pre class="programlisting"><span class="comment">/** Asynchronously read a line and echo it back.

    This function is used to asynchronously read a line ending
    in a newline (`"\n"`) from the stream, and then write
    it back.

    This call always returns immediately. The asynchronous operation
    will continue until one of the following conditions is true:

    @li A line was read in and written back on the stream

    @li An error occurs.

    The algorithm, known as a &lt;em&gt;composed asynchronous operation&lt;/em&gt;,
    is implemented in terms of calls to the stream's `async_read_some`
    and `async_write_some` function. The program must ensure that no
    other reads or writes are performed until this operation completes.

    Since the length of the line is not known ahead of time, the
    implementation may read additional characters that lie past the
    first line. These characters are stored in the dynamic buffer_.
    The same dynamic buffer must be presented again in each call,
    to provide the implementation with any leftover bytes.

    @param stream The stream to operate on. The type must meet the
    requirements of &lt;em&gt;AsyncReadStream&lt;/em&gt; and @AsyncWriteStream

    @param buffer A dynamic buffer to hold implementation-defined
    temporary data. Ownership is not transferred; the caller is
    responsible for ensuring that the lifetime of this object is
    extended least until the completion handler is invoked.

    @param token The handler to be called when the operation completes.
    The implementation takes ownership of the handler by performing a decay-copy.
    The handler must be invocable with this signature:
    @code
    void handler(
        beast::error_code error      // Result of operation.
    );
    @endcode

    Regardless of whether the asynchronous operation completes immediately or
    not, the handler will not be invoked from within this function. Invocation
    of the handler will be performed in a manner equivalent to using
    `net::post`.
*/</span>
<span class="keyword">template</span><span class="special">&lt;</span>
    <span class="keyword">class</span> <span class="identifier">AsyncStream</span><span class="special">,</span>
    <span class="keyword">class</span> <span class="identifier">DynamicBuffer</span><span class="special">,</span>
    <span class="keyword">class</span> <span class="identifier">CompletionToken</span><span class="special">&gt;</span>
<span class="keyword">auto</span>
<span class="identifier">async_echo</span> <span class="special">(</span>
    <span class="identifier">AsyncStream</span><span class="special">&amp;</span> <span class="identifier">stream</span><span class="special">,</span>
    <span class="identifier">DynamicBuffer</span><span class="special">&amp;</span> <span class="identifier">buffer</span><span class="special">,</span> <a class="co" name="beast.using_io.writing_composed_operations.echo.c0" href="echo.html#beast.using_io.writing_composed_operations.echo.c1"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a>
    <span class="identifier">CompletionToken</span><span class="special">&amp;&amp;</span> <span class="identifier">token</span><span class="special">)</span> <span class="special">-&gt;</span>
        <span class="keyword">typename</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_result</span><span class="special">&lt;</span> <a class="co" name="beast.using_io.writing_composed_operations.echo.c2" href="echo.html#beast.using_io.writing_composed_operations.echo.c3"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a>
            <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay</span><span class="special">&lt;</span><span class="identifier">CompletionToken</span><span class="special">&gt;::</span><span class="identifier">type</span><span class="special">,</span>
            <span class="keyword">void</span><span class="special">(</span><span class="identifier">beast</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">)</span> <a class="co" name="beast.using_io.writing_composed_operations.echo.c4" href="echo.html#beast.using_io.writing_composed_operations.echo.c5"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a>
                <span class="special">&gt;::</span><span class="identifier">return_type</span><span class="special">;</span>
</pre>
<div class="calloutlist"><table border="0" summary="Callout list">
<tr>
<td width="5%" valign="top" align="left"><p><a name="beast.using_io.writing_composed_operations.echo.c1"></a><a href="#beast.using_io.writing_composed_operations.echo.c0"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td>
<td valign="top" align="left"><p>
              Unlike Asio, we pass by non-const reference instead of rvalue-ref
            </p></td>
</tr>
<tr>
<td width="5%" valign="top" align="left"><p><a name="beast.using_io.writing_composed_operations.echo.c3"></a><a href="#beast.using_io.writing_composed_operations.echo.c2"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td>
<td valign="top" align="left"><p>
              <code class="computeroutput"><span class="identifier">async_result</span></code> deduces
              the return type from the completion handler
            </p></td>
</tr>
<tr>
<td width="5%" valign="top" align="left"><p><a name="beast.using_io.writing_composed_operations.echo.c5"></a><a href="#beast.using_io.writing_composed_operations.echo.c4"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> </p></td>
<td valign="top" align="left"><p>
              The completion handler signature goes here
            </p></td>
</tr>
</table></div>
<p>
          Now that we have a declaration, we will define the body of the function.
          We want to achieve the following goals: perform static type checking on
          the input parameters, set up the return value as per <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf" target="_top"><span class="bold"><strong>N3747</strong></span></a>, and launch the composed operation
          by constructing an intermediate, stateful completion handler and invoking
          it.
        </p>
<p>
          The initiating function contains a few relatively simple parts. There is
          the customization of the return value type, static type checking, building
          the return value type using the helper, and creating and launching the
          <code class="computeroutput"><span class="identifier">echo_op</span></code> composed operation
          object.
        </p>
<p>
          The implementation strategy is to make the composed object meet the requirements
          of a completion handler by being movable, and by making it invocable so
          it can be used as a continuation for the asynchronous operations it launches.
          Rather than using <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span></code> or <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span></code>,
          which destroys the type information and therefore breaks the allocation
          and invocation hooks, we will simply pass <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)</span></code>
          as the completion handler parameter for any operations that we initiate.
          For the move to work correctly, care must be taken to ensure that no access
          to data members are made after the move takes place. Here is the complete
          implementation of our composed operation:
        </p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">AsyncStream</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Handler</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">echo_op</span><span class="special">;</span>

<span class="comment">// This example uses the Asio's stackless "fauxroutines", implemented</span>
<span class="comment">// using a macro-based solution. It makes the code easier to write and</span>
<span class="comment">// easier to read. This include file defines the necessary macros and types.</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">asio</span><span class="special">/</span><span class="identifier">yield</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="comment">// Read a line and echo it back</span>
<span class="comment">//</span>
<span class="keyword">template</span><span class="special">&lt;</span>
    <span class="keyword">class</span> <span class="identifier">AsyncStream</span><span class="special">,</span>
    <span class="keyword">class</span> <span class="identifier">DynamicBuffer</span><span class="special">,</span>
    <span class="keyword">class</span> <span class="identifier">CompletionToken</span><span class="special">&gt;</span>
<span class="keyword">auto</span>
<span class="identifier">async_echo</span><span class="special">(</span>
    <span class="identifier">AsyncStream</span><span class="special">&amp;</span> <span class="identifier">stream</span><span class="special">,</span>
    <span class="identifier">DynamicBuffer</span><span class="special">&amp;</span> <span class="identifier">buffer</span><span class="special">,</span>
    <span class="identifier">CompletionToken</span><span class="special">&amp;&amp;</span> <span class="identifier">token</span><span class="special">)</span> <span class="special">-&gt;</span>
        <span class="keyword">typename</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_result</span><span class="special">&lt;</span>
            <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay</span><span class="special">&lt;</span><span class="identifier">CompletionToken</span><span class="special">&gt;::</span><span class="identifier">type</span><span class="special">,</span>
            <span class="keyword">void</span><span class="special">(</span><span class="identifier">beast</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">)&gt;::</span><span class="identifier">return_type</span> <a class="co" name="beast.using_io.writing_composed_operations.echo.c6" href="echo.html#beast.using_io.writing_composed_operations.echo.c7"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a>
<span class="special">{</span>
    <span class="comment">// Perform some type checks using static assert, this helps</span>
    <span class="comment">// with more friendly error messages when passing the wrong types.</span>
    <span class="keyword">static_assert</span><span class="special">(</span>
        <span class="identifier">beast</span><span class="special">::</span><span class="identifier">is_async_stream</span><span class="special">&lt;</span><span class="identifier">AsyncStream</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">,</span>
        <span class="string">"AsyncStream type requirements not met"</span><span class="special">);</span>
    <span class="keyword">static_assert</span><span class="special">(</span>
        <span class="identifier">net</span><span class="special">::</span><span class="identifier">is_dynamic_buffer</span><span class="special">&lt;</span><span class="identifier">DynamicBuffer</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">,</span>
        <span class="string">"DynamicBuffer type requirements not met"</span><span class="special">);</span>

    <span class="comment">// This class template deduces the actual handler type from a</span>
    <span class="comment">// CompletionToken, captures a local reference to the handler,</span>
    <span class="comment">// and creates the `async_result` object which becomes the</span>
    <span class="comment">// return value of this initiating function.</span>

    <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_completion</span><span class="special">&lt;</span><span class="identifier">CompletionToken</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="identifier">beast</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">)&gt;</span> <span class="identifier">init</span><span class="special">(</span><span class="identifier">token</span><span class="special">);</span>

    <span class="comment">// The helper macro BOOST_ASIO_HANDLER_TYPE converts the completion</span>
    <span class="comment">// token type into a concrete handler type of the correct signature.</span>

    <span class="keyword">using</span> <span class="identifier">handler_type</span> <span class="special">=</span> <span class="identifier">BOOST_ASIO_HANDLER_TYPE</span><span class="special">(</span><span class="identifier">CompletionToken</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="identifier">beast</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">));</span>

    <span class="comment">// The class template `async_base` holds the caller's completion</span>
    <span class="comment">// handler for us, and provides all of the boilerplate for forwarding</span>
    <span class="comment">// the associated allocator and associated executor from the caller's</span>
    <span class="comment">// handler to our operation. It also maintains a `net::executor_work_guard`</span>
    <span class="comment">// for the executor associated with the stream. This work guard is</span>
    <span class="comment">// inexpensive, and prevents the execution context from running out</span>
    <span class="comment">// of work. It is usually necessary although rarely it can be skipped</span>
    <span class="comment">// depending on the operation (this echo example needs it because it</span>
    <span class="comment">// performs more than one asynchronous operation in a row).</span>
    <span class="comment">// We declare this type alias to make the code easier to read.</span>

    <span class="keyword">using</span> <span class="identifier">base_type</span> <span class="special">=</span> <span class="identifier">beast</span><span class="special">::</span><span class="identifier">async_base</span><span class="special">&lt;</span>
        <span class="identifier">handler_type</span><span class="special">,</span> <a class="co" name="beast.using_io.writing_composed_operations.echo.c8" href="echo.html#beast.using_io.writing_composed_operations.echo.c9"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a>
        <span class="identifier">beast</span><span class="special">::</span><span class="identifier">executor_type</span><span class="special">&lt;</span><span class="identifier">AsyncStream</span><span class="special">&gt;</span> <a class="co" name="beast.using_io.writing_composed_operations.echo.c10" href="echo.html#beast.using_io.writing_composed_operations.echo.c11"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a>
    <span class="special">&gt;;</span>

    <span class="comment">// This nested class implements the echo composed operation as a</span>
    <span class="comment">// stateful completion handler. We derive from `async_base` to</span>
    <span class="comment">// take care of boilerplate and we derived from asio::coroutine to</span>
    <span class="comment">// allow the reenter and yield keywords to work.</span>

    <span class="keyword">struct</span> <span class="identifier">echo_op</span> <span class="special">:</span> <span class="identifier">base_type</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">coroutine</span>
    <span class="special">{</span>
        <span class="identifier">AsyncStream</span><span class="special">&amp;</span> <span class="identifier">stream_</span><span class="special">;</span>
        <span class="identifier">DynamicBuffer</span><span class="special">&amp;</span> <span class="identifier">buffer_</span><span class="special">;</span>

        <span class="identifier">echo_op</span><span class="special">(</span>
            <span class="identifier">AsyncStream</span><span class="special">&amp;</span> <span class="identifier">stream</span><span class="special">,</span>
            <span class="identifier">DynamicBuffer</span><span class="special">&amp;</span> <span class="identifier">buffer</span><span class="special">,</span>
            <span class="identifier">handler_type</span><span class="special">&amp;&amp;</span> <span class="identifier">handler</span><span class="special">)</span>
            <span class="special">:</span> <span class="identifier">base_type</span><span class="special">(</span>
                <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">handler</span><span class="special">),</span> <a class="co" name="beast.using_io.writing_composed_operations.echo.c12" href="echo.html#beast.using_io.writing_composed_operations.echo.c13"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a>
                <span class="identifier">stream</span><span class="special">.</span><span class="identifier">get_executor</span><span class="special">())</span> <a class="co" name="beast.using_io.writing_composed_operations.echo.c14" href="echo.html#beast.using_io.writing_composed_operations.echo.c15"><img src="../../../../../../../doc/src/images/callouts/5.png" alt="5" border="0"></a>
            <span class="special">,</span> <span class="identifier">stream_</span><span class="special">(</span><span class="identifier">stream</span><span class="special">)</span>
            <span class="special">,</span> <span class="identifier">buffer_</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">)</span>
        <span class="special">{</span>
            <span class="comment">// Launch the operation directly from the constructor. We</span>
            <span class="comment">// pass `false` for `cont` to indicate that the calling</span>
            <span class="comment">// thread does not represent a continuation of our</span>
            <span class="comment">// asynchronous control flow.</span>
            <span class="special">(*</span><span class="keyword">this</span><span class="special">)({},</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">false</span><span class="special">);</span>
        <span class="special">}</span>

        <span class="comment">// If a newline is present in the buffer sequence, this function returns</span>
        <span class="comment">// the number of characters from the beginning of the buffer up to the</span>
        <span class="comment">// newline, including the newline character. Otherwise it returns zero.</span>

        <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span>
        <span class="identifier">find_newline</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">DynamicBuffer</span><span class="special">::</span><span class="identifier">const_buffers_type</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">buffers</span><span class="special">)</span>
        <span class="special">{</span>
            <span class="comment">// The `buffers_iterator` class template provides random-access</span>
            <span class="comment">// iterators into a buffer sequence. Use the standard algorithm</span>
            <span class="comment">// to look for the new line if it exists.</span>

            <span class="keyword">auto</span> <span class="identifier">begin</span> <span class="special">=</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">buffers_iterator</span><span class="special">&lt;</span>
                <span class="keyword">typename</span> <span class="identifier">DynamicBuffer</span><span class="special">::</span><span class="identifier">const_buffers_type</span><span class="special">&gt;::</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">buffers</span><span class="special">);</span>
            <span class="keyword">auto</span> <span class="identifier">end</span> <span class="special">=</span>   <span class="identifier">net</span><span class="special">::</span><span class="identifier">buffers_iterator</span><span class="special">&lt;</span>
                <span class="keyword">typename</span> <span class="identifier">DynamicBuffer</span><span class="special">::</span><span class="identifier">const_buffers_type</span><span class="special">&gt;::</span><span class="identifier">end</span><span class="special">(</span><span class="identifier">buffers</span><span class="special">);</span>
            <span class="keyword">auto</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">find</span><span class="special">(</span><span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">,</span> <span class="char">'\n'</span><span class="special">);</span>

            <span class="keyword">if</span><span class="special">(</span><span class="identifier">result</span> <span class="special">==</span> <span class="identifier">end</span><span class="special">)</span>
                <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> <span class="comment">// not found</span>

            <span class="keyword">return</span> <span class="identifier">result</span> <span class="special">+</span> <span class="number">1</span> <span class="special">-</span> <span class="identifier">begin</span><span class="special">;</span>
        <span class="special">}</span>

        <span class="comment">// This is the entry point of our completion handler. Every time an</span>
        <span class="comment">// asynchronous operation completes, this function will be invoked.</span>

        <span class="keyword">void</span>
        <span class="keyword">operator</span><span class="special">()(</span>
            <span class="identifier">beast</span><span class="special">::</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">,</span>
            <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">bytes_transferred</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span>
            <span class="keyword">bool</span> <span class="identifier">cont</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">)</span> <span class="comment">/*&lt; Second and subsequent invocations will seee `cont=true`. */</span>
        <span class="special">{</span>
            <span class="comment">// The `reenter` keyword transfers control to the last</span>
            <span class="comment">// yield point, or to the beginning of the scope if</span>
            <span class="comment">// this is the first time.</span>

            <span class="identifier">reenter</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)</span>
            <span class="special">{</span>
                <span class="keyword">for</span><span class="special">(;;)</span>
                <span class="special">{</span>
                    <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">pos</span><span class="special">;</span>

                    <span class="comment">// Search for a newline in the readable bytes of the buffer</span>
                    <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">find_newline</span><span class="special">(</span><span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">data</span><span class="special">());</span>

                    <span class="comment">// If we don't have the newline, then read more</span>
                    <span class="keyword">if</span><span class="special">(</span><span class="identifier">pos</span> <span class="special">==</span> <span class="number">0</span><span class="special">)</span>
                    <span class="special">{</span>
                        <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">bytes_to_read</span><span class="special">;</span>

                        <span class="comment">// Determine the number of bytes to read,</span>
                        <span class="comment">// using available capacity in the buffer first.</span>

                        <span class="identifier">bytes_to_read</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">min</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">&gt;(</span>
                              <span class="identifier">std</span><span class="special">::</span><span class="identifier">max</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">&gt;(</span><span class="number">512</span><span class="special">,</span>                <span class="comment">// under 512 is too little,</span>
                                  <span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">capacity</span><span class="special">()</span> <span class="special">-</span> <span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">size</span><span class="special">()),</span>
                              <span class="identifier">std</span><span class="special">::</span><span class="identifier">min</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">&gt;(</span><span class="number">65536</span><span class="special">,</span>              <span class="comment">// and over 65536 is too much.</span>
                                  <span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">max_size</span><span class="special">()</span> <span class="special">-</span> <span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">size</span><span class="special">()));</span>

                        <span class="comment">// Read some data into our dynamic buffer_. We transfer</span>
                        <span class="comment">// ownership of the composed operation by using the</span>
                        <span class="comment">// `std::move(*this)` idiom. The `yield` keyword causes</span>
                        <span class="comment">// the function to return immediately after the initiating</span>
                        <span class="comment">// function returns.</span>

                        <span class="identifier">yield</span> <span class="identifier">stream_</span><span class="special">.</span><span class="identifier">async_read_some</span><span class="special">(</span>
                            <span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">prepare</span><span class="special">(</span><span class="identifier">bytes_to_read</span><span class="special">),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(*</span><span class="keyword">this</span><span class="special">));</span>

                        <span class="comment">// After the `async_read_some` completes, control is</span>
                        <span class="comment">// transferred to this line by the `reenter` keyword.</span>

                        <span class="comment">// Move the bytes read from the writable area to the</span>
                        <span class="comment">// readable area.</span>

                        <span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">commit</span><span class="special">(</span><span class="identifier">bytes_transferred</span><span class="special">);</span>

                        <span class="comment">// If an error occurs, deliver it to the caller's completion handler.</span>
                        <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
                            <span class="keyword">break</span><span class="special">;</span>

                        <span class="comment">// Keep looping until we get the newline</span>
                        <span class="keyword">continue</span><span class="special">;</span>
                    <span class="special">}</span>

                    <span class="comment">// We have our newline, so send the first `pos` bytes of the</span>
                    <span class="comment">// buffers. The function `buffers_prefix` returns the front part</span>
                    <span class="comment">// of the buffers we want.</span>

                    <span class="identifier">yield</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">stream_</span><span class="special">,</span>
                        <span class="identifier">beast</span><span class="special">::</span><span class="identifier">buffers_prefix</span><span class="special">(</span><span class="identifier">pos</span><span class="special">,</span> <span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">data</span><span class="special">()),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(*</span><span class="keyword">this</span><span class="special">));</span>

                    <span class="comment">// After the `async_write` completes, our completion handler will</span>
                    <span class="comment">// be invoked with the error and the number of bytes transferred,</span>
                    <span class="comment">// and the `reenter` statement above will cause control to jump</span>
                    <span class="comment">// to the following line. The variable `pos` is no longer valid</span>
                    <span class="comment">// (remember that we returned from the function using `yield` above)</span>
                    <span class="comment">// but we can use `bytes_transferred` to know how much of the buffer</span>
                    <span class="comment">// to consume. With "real" coroutines this will be easier and more</span>
                    <span class="comment">// natural.</span>

                    <span class="identifier">buffer_</span><span class="special">.</span><span class="identifier">consume</span><span class="special">(</span><span class="identifier">bytes_transferred</span><span class="special">);</span>

                    <span class="comment">// The loop terminates here, and we will either deliver a</span>
                    <span class="comment">// successful result or an error to the caller's completion handler.</span>

                    <span class="keyword">break</span><span class="special">;</span>
                <span class="special">}</span>

                <span class="comment">// When a composed operation completes immediately, it must not</span>
                <span class="comment">// directly invoke the completion handler otherwise it could</span>
                <span class="comment">// lead to unfairness, starvation, or stack overflow. Therefore,</span>
                <span class="comment">// if cont == false (meaning, that the call stack still includes</span>
                <span class="comment">// the frame of the initiating function) then we need to use</span>
                <span class="comment">// `net::post` to cause us to be called again after the initiating</span>
                <span class="comment">// function. The function `async_base::invoke` takes care of</span>
                <span class="comment">// calling the final completion handler, using post if the</span>
                <span class="comment">// first argument is false, otherwise invoking it directly.</span>

                <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">complete</span><span class="special">(</span><span class="identifier">cont</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span>
            <span class="special">}</span>
        <span class="special">}</span>
    <span class="special">};</span>

    <span class="comment">// Create the composed operation and launch it. This is a constructor</span>
    <span class="comment">// call followed by invocation of operator(). We use BOOST_ASIO_HANDLER_TYPE</span>
    <span class="comment">// to convert the completion token into the correct handler type,</span>
    <span class="comment">// allowing user-defined specializations of the async_result template</span>
    <span class="comment">// to be used.</span>

    <span class="identifier">echo_op</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">buffer</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">init</span><span class="special">.</span><span class="identifier">completion_handler</span><span class="special">));</span>

    <span class="comment">// This hook lets the caller see a return value when appropriate.</span>
    <span class="comment">// For example this might return std::future&lt;error_code&gt; if</span>
    <span class="comment">// CompletionToken is net::use_future, or this might</span>
    <span class="comment">// return an error code if CompletionToken specifies a coroutine.</span>

    <span class="keyword">return</span> <span class="identifier">init</span><span class="special">.</span><span class="identifier">result</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span>
<span class="special">}</span>

<span class="comment">// Including this file undefines the macros used by the stackless fauxroutines.</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">asio</span><span class="special">/</span><span class="identifier">unyield</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<div class="calloutlist"><table border="0" summary="Callout list">
<tr>
<td width="5%" valign="top" align="left"><p><a name="beast.using_io.writing_composed_operations.echo.c7"></a><a href="#beast.using_io.writing_composed_operations.echo.c6"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td>
<td valign="top" align="left"><p>
              The completion handler signature goes here
            </p></td>
</tr>
<tr>
<td width="5%" valign="top" align="left"><p><a name="beast.using_io.writing_composed_operations.echo.c9"></a><a href="#beast.using_io.writing_composed_operations.echo.c8"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td>
<td valign="top" align="left"><p>
              The type of the completion handler obtained from the token
            </p></td>
</tr>
<tr>
<td width="5%" valign="top" align="left"><p><a name="beast.using_io.writing_composed_operations.echo.c11"></a><a href="#beast.using_io.writing_composed_operations.echo.c10"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> </p></td>
<td valign="top" align="left"><p>
              The type of executor used by the stream to dispatch asynchronous operations
            </p></td>
</tr>
<tr>
<td width="5%" valign="top" align="left"><p><a name="beast.using_io.writing_composed_operations.echo.c13"></a><a href="#beast.using_io.writing_composed_operations.echo.c12"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a> </p></td>
<td valign="top" align="left"><p>
              The <code class="computeroutput"><span class="identifier">async_base</span></code> helper
              takes ownership of the handler,
            </p></td>
</tr>
<tr>
<td width="5%" valign="top" align="left"><p><a name="beast.using_io.writing_composed_operations.echo.c15"></a><a href="#beast.using_io.writing_composed_operations.echo.c14"><img src="../../../../../../../doc/src/images/callouts/5.png" alt="5" border="0"></a> </p></td>
<td valign="top" align="left"><p>
              and also needs to know which executor to use.
            </p></td>
</tr>
</table></div>
<p>
          There are some common mistakes that should be avoided when writing composed
          operations:
        </p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
              Type erasing the final handler. This will cause undefined behavior.
            </li>
<li class="listitem">
              Forgetting to include a return statement after calling an initiating
              function.
            </li>
<li class="listitem">
              Calling a synchronous function by accident. In general composed operations
              should not block for long periods of time, since this ties up a thread
              running on the <a href="../../../../../../../doc/html/boost_asio/reference/io_context.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">io_context</span></code></a>.
            </li>
<li class="listitem">
              Forgetting to provide <code class="computeroutput"><span class="identifier">executor_type</span></code>
              and <code class="computeroutput"><span class="identifier">get_executor</span></code> for
              the composed operation. This will cause undefined behavior. For example,
              if someone calls the initiating function with a strand-wrapped function
              object, and there is more than thread running on the <a href="../../../../../../../doc/html/boost_asio/reference/io_context.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">io_context</span></code></a>, the underlying
              stream may be accessed in a fashion that violates safety guarantees.
              Beast provides class templates to take care of this boilerplate for
              you.
            </li>
<li class="listitem">
              Forgetting to create an object of type <a href="../../../../../../../doc/html/boost_asio/reference/executor_work_guard.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">executor_work_guard</span></code></a> with
              the type of executor returned by the stream's <code class="computeroutput"><span class="identifier">get_executor</span></code>
              member function.
            </li>
<li class="listitem">
              For operations which complete immediately (i.e. without calling an
              intermediate initiating function), forgetting to use <a href="../../../../../../../doc/html/boost_asio/reference/post.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">post</span></code></a> to invoke the final
              handler. This breaks the following initiating function guarantee:
              <span class="emphasis"><em>Regardless of whether the asynchronous operation completes
              immediately or not, the handler will not be invoked from within this
              function. Invocation of the handler will be performed in a manner equivalent
              to using <a href="../../../../../../../doc/html/boost_asio/reference/post.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">post</span></code></a></em></span>. The function
              <a class="link" href="../../ref/boost__beast__bind_handler.html" title="bind_handler"><code class="computeroutput"><span class="identifier">bind_handler</span></code></a> is provided for
              this purpose.
            </li>
</ul></div>
<p>
          The listing for a complete, runnable version of this example is in <a href="../../../../../example/echo-op/echo_op.cpp" target="_top">echo_op.cpp</a>.
        </p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2016-2019 Vinnie
      Falco<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../writing_composed_operations.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../writing_composed_operations.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="detect_ssl.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
